#!/usr/bin/perl -w

# Copyright 2008 Jordi Carrillo
# Renaming, tagging and commenting a bunch of photos
# from my travels before uploading them to FlickR

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


use Getopt::Std;
use File::Find;
use File::Basename;
use Image::ExifTool qw(:Public);
use strict;


################################################
# Main ####


my %opts=();
my %images=();

my $exif = new Image::ExifTool;
my $dobackup = undef;
my $getjpgs = undef;

getOptions();

# path is mandatory in all cases
# to process images
my $path=$opts{"p"};

if (defined $getjpgs) {
    getImages();
    exit(0);
}

my $newname=$opts{"n"};
my $count=$opts{"c"};
my $tags=$opts{"t"};
my $summary=$opts{"s"};
my @keywords = split(/,/,$tags);

if (defined $dobackup) {
    print "backup option provided\n";
    backup($path);
}

my $ok = verify();
if (not defined $ok) {
    print "aborted by user\n";
    exit(-1);
}
process();
printValues();
exit(0);


################################################


# sub verify

sub verify
{
    print "=============== Verify ==================\n\n";
    while (my ($key,$value)= each %opts) {
        print "newname is $value\n" if ($key eq "n");
        print "begins counting at $value\n" if ($key eq "c");
        print "directory of pictures is $value\n" if ($key eq "p");
        print "comment provided is $value\n" if ($key eq "s");
    }
    my $tags = $opts{"t"};
    my @keywords=split(/,/,$tags);
    print "tags provided are @keywords\n";
    my $yn;
    print "is that fine? (y/n)\n";
    chomp ($yn=<STDIN>);
    if ($yn eq "y") {

        return "true";
    }
    else {
        return undef;
    }

}

# subroutine backup
# params
# summary makes a tar backup of all pictures
# before tagging and commenting them all

sub backup
{
    my $path = shift;
    print "backup name: \n";
    chomp (my $backupname = <STDIN>);
    print "backing up...";
    my @res = `tar -czvf $backupname -P $path`;
    open LOG,">out.log";
    print LOG $_ foreach (@res);
    close LOG;
    print "backup finished\n";
    print "log in out.log and backup in your $ENV{'HOME'}\n";
}

sub getImages {
    find(\&getJpgs,$path);
}


# subroutine process
# params 
# summary processes all the pictures
# just calls getImages that will tag all the pictures
# as provided in the command line

sub process 
{
    find(\&tagImages,$path);
}

# subroutine printValues
# params
# summary Will rename and print some verbose information

sub printValues 
{
    my $number = $count;
    my @pathfilesordered = sort { $images{$a} cmp $images{$b} } keys %images;
    foreach my $file (@pathfilesordered) {
        my $newfilename = dirname($file)."/".$newname."_".$number++.".jpg";
        if (-e $newfilename ) {
            print "new file name already exists, aborted\n";
            exit (-1);
        }
        print "renaming $file to $newfilename\n";
        rename $file,$newfilename;
    }
    my $numrenamed = $number-$count;
    print "Number of pics renamed are: $numrenamed\n";
}


sub tagImages 
{
    my $pathfile = $File::Find::name;
    my $curdir = $File::Find::dir;
    if (-f $pathfile && $pathfile =~ /.*\.jpg$/i) {
        my $success=$exif->ExtractInfo($pathfile);
        $pathfile =~ /\w?(\d+).*/;
        $images{$pathfile} = $1;
        $exif->SetNewValue('Subject',\@keywords);
        $exif->SetNewValue('UserComment', $summary);
        print "tagging $pathfile\n";
        $exif->WriteInfo($pathfile);
        $exif->SetNewValue();
    
    }
    
}

# prints all the images found
# to standard output. That's it, no further
# processing
#
sub getJpgs {
    my $pathfile = $File::Find::name;
    if (-f $pathfile && $pathfile =~ /.*\.jpg$/i) {
        print "$pathfile\n";
    }
}


sub usage
{
    print <<"EOF";
    Usage:
        ./ptager -b -p fullpath -n newname -c count -t commaseparatedtags -s comment
EOF
    exit(0);
}

sub usage2
{
    print <<EOF;
    To get a list of files without further processing just type:
        ./ptager -g -p fullpath
EOF
    exit(0);
}


sub getOptions
{

    # backup option added -b
    # although should be mandatory

    getopts('gbn:c:p:t:s:',\%opts);

    # Checking if mandatory options are provided

    my @options = qw /n c p t s/;
    
    if (exists $opts{'g'}) {
        # get images and finish
        $getjpgs = 'true';
        # path must be provided
        if (not exists $opts{'p'}) {
            usage2();
        }
        return;
    }
    foreach (@options) {
        if (not exists $opts{$_}) {
            print "I'm missing mandatory options\n";
            usage();
        }
    }

    # optional backup provided?

    if (exists $opts{'b'}) {
        $dobackup = 'true';
        return;
    }
    else {
        return;
    }
    
}

=head1 NAME

ptager - Renames, tags and comments digital pictures jpg

=head1 SYNOPSIS

B<ptager> [I<OPTIONS>] 

=head1 MANDATORY OPTIONS

=over

=item B<->I<p> 

Full path to the pictures i.e. /home/username/pictures 

=item B<->I<c>

Number by which we will begin to rename our pictures newname_0, newname_1

=item B<->I<n> 

newname for the pictures

=item B<->I<t> 

comma separated tags 

=item B<->I<s> 

Summary, or comment for the pictures. Enclose the comment with quotes

=back

=head1 OPTIONAL

=over

=item B<->I<b> 

Performs a tar gzipped backup before tagging and renaming

=back

=head1 EXAMPLES

=over

=item ptager -b -p /home/name/Pics/tvl2008 -n bcn2008 -c 2 -t BCN,2008,July -s ''My travel to Barcelona July 2008''

This will perform a backup in current directory and then it will rename, tag and comment all the pictures under the provided path as follows:

bcn2008_2.jpg

bcn2008_3.jpg

bcn2008_4.jpg

bcn2008_5.jpg

=back

=head1 AUTHOR

Copyright 2008, Jordi Carrillo

This is free software; you can redistribute it and/or modify it under the
same terms as Perl itself.

=cut 
